/**************************************************************************************************
**                                                                                               **
**  文件名称:  nft_toolsbox.c                                                                    **
**  版权所有:  CopyRight @ Xiamen Yaxon NetWork CO.LTD. 2017                                     **
**  文件描述:  各类工具函数                                                                      **
**  ===========================================================================================  **
**  创建信息:  | 2017-3-20 | LEON | 创建本模块                                                   **
**  ===========================================================================================  **
**  修改信息:  单击此处添加....                                                                  **
**************************************************************************************************/
#include "nft_include.h"
#include "nft_toolsbox.h"

/*************************************************************************************************/
/*                           模块静态变量定义                                                    */
/*************************************************************************************************/
static const INT8U s_month[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

/**************************************************************************************************
**  函数名称:  TOOL_SystemDelay
**  功能描述:  系统强制延时函数
**  输入参数:  无
**  输出参数:  无
**  返回参数:  无
**************************************************************************************************/
void TOOL_SystemDelayms(INT32U msec)
{
    INT32U count = 0;
    INT32U mtime = 35 * 1000 * msec;
    
    do {
        if (++count > mtime) {
            return;
        }
    } while (1);
}

/**************************************************************************************************
**  函数名称:  UpperChar
**  功能描述:  字符变成大写
**  输入参数:  无
**  输出参数:  无
**  返回参数:  无
**************************************************************************************************/
INT8U TOOL_UpperChar(INT8U ch)
{
    if (ch >= 'a' && ch <= 'z') {
        ch = 'A' + (ch - 'a');
    }
    
    return ch;
}

/**************************************************************************************************
**  函数名称:  LowerChar
**  功能描述:  字符变成小写
**  输入参数:  无
**  输出参数:  无
**  返回参数:  无
**************************************************************************************************/
INT8U TOOL_LowerChar(INT8U ch)
{
    if (ch >= 'A' && ch <= 'Z'){
        ch = 'a' + (ch - 'A');
    }
    
    return ch;
}

/**************************************************************************************************
**  函数名称:  TOOL_CompareChar
**  功能描述:  比较字符大小
**  输入参数:  无
**  输出参数:  无
**  返回参数:  无
**************************************************************************************************/
INT8U TOOL_CompareChar(BOOLEAN matchcase, INT8U ch1, INT8U ch2)
{
    if (matchcase != CASESENSITIVE) {
        ch1 = TOOL_UpperChar(ch1);
        ch2 = TOOL_UpperChar(ch2);
    }
    
    if (ch1 > ch2) {
       return STR_GREAT;
    } else if (ch1 < ch2) {
       return STR_LESS;
    } else {
       return STR_EQUAL;
    }
}

/**************************************************************************************************
**  函数名称:  TOOL_CompareString
**  功能描述:  比较字符串大小
**  输入参数:  无
**  输出参数:  无
**  返回参数:  无
**************************************************************************************************/
INT8U TOOL_CompareString(BOOLEAN matchcase, INT8U *ptr1, INT8U *ptr2, INT16U len1, INT16U len2)
{
    INT8U result;
    
    for (;;) {
        
        if (len1 == 0 && len2 == 0) return STR_EQUAL;
        if (len1 == 0) return STR_LESS;
        if (len2 == 0) return STR_GREAT;
        
        result = TOOL_CompareChar(matchcase, *ptr1++, *ptr2++);
        
        if (result != STR_EQUAL) {
            return result;
        } else {
            len1--;
            len2--;
        }
    }
}

/**************************************************************************************************
**  函数名称:  TOOL_HexToChar
**  功能描述:  将输入16进制字节数据的低4位值转换成字符
**  输入参数:  inbyte: 输入字节
**  输出参数:  无
**  返回参数:  字符
**************************************************************************************************/
INT8U TOOL_HexToChar(INT8U inbyte)
{
    INT8U temp;
    
    temp = inbyte & 0x0F;
    
    if (temp < 0x0A) {
        return (temp + '0');
    } else {
        return (temp - 0x0A + 'A');
    }
}

/**************************************************************************************************
**  函数名称:  TOOL_CharToHex
**  功能描述:  将输入字符转化成16进制字节数据
**  输入参数:  inchar: 输入字符
**  输出参数:  无
**  返回参数:  16进制值
**************************************************************************************************/
INT8U TOOL_CharToHex(INT8U inchar)
{
    if (inchar >= '0' && inchar <= '9') {
        return (inchar - '0');
    } else if (inchar >= 'A' && inchar <= 'F') {
        return (inchar - 'A' + 0x0A);
    } else if (inchar >= 'a' && inchar <= 'f') {
        return (inchar - 'a' + 0x0A);
    } else {
        return 0;
    }
}

/**************************************************************************************************
**  函数名称:  Hex8UtoAlg16U
**  功能描述:  单字节的16进制转换为双字节的10进制形式表示(例如输入0xff，转换后将输出0x255)
**  输入参数:  INT8U data
**  输出参数:  无
**  输出参数:  INT16U
**************************************************************************************************/
INT16U TOOL_Hex8UtoAlg16U(INT8U data)
{
	return ((data / 100) * 256 + (data % 100) / 10 * 16 + (data % 10));
}

/**************************************************************************************************
**  函数名称:  Hex16UtoAlg32U
**  功能描述:  双字节的16进制转换为四字节的10进制形式表示(例如输入0xffff，转换后将输出0x65535)
**  输入参数:  INT16U data
**  输出参数:  无
**  输出参数:  INT32U
**************************************************************************************************/
INT32U TOOL_Hex16UtoAlg32U(INT16U data)
{
	return ((data / 10000) * 65536 + (data % 10000) / 1000 * 4096 + 
	        (data % 1000) / 100 * 256 + (data % 100) / 10 * 16 + (data % 10));
}

/**************************************************************************************************
**  函数名称:  Alg16UtoHex8U
**  功能描述:  双字节的10进制转换为单字节的16进制形式表示(例如输入0x255，转换后将输出0xff)
**  输入参数:  INT16U data
**  输出参数:  无
**  输出参数:  INT8U
**************************************************************************************************/
INT8U TOOL_Alg16UtoHex8U(INT16U data)
{
	INT16U temp;

	if (data >= 0x256) {
        return 0;                                                              /* 输入数据不能大于0x256 */
	}
    
	temp = ((data / 256) * 100 + (data % 256) / 16 * 10 + (data % 16));
    
	return (INT8U)temp;
}

/**************************************************************************************************
**  函数名称:  Alg32UtoHex16U
**  功能描述:  四字节的10进制转换为双字节的16进制形式表示(例如输入0x65535，转换后将输出0xffff)
**  输入参数:  INT32U data
**  输出参数:  无
**  输出参数:  INT16U
**************************************************************************************************/
INT16U TOOL_Alg32UtoHex16U(INT32U data)
{
	INT32U temp;

	if (data >= 0x65536) {
        return 0;                                                              /*  输入数据不能大于0x65536 */
	}
    
	temp = ((data / 65536) * 10000 + (data % 65536) / 4096 * 1000 + 
	        (data % 4096) / 256 * 100 + (data % 256) / 16 * 10 + (data % 16));
    
	return (INT16U)temp;
}

/**************************************************************************************************
**  函数名称:  TOOL_AsciiToDec
**  功能描述:  将ASCII字符串转换成十进制数据['7','8','9','9' -----> 7899]
**  输入参数:  无
**  输出参数:  无
**  返回参数:  无
**************************************************************************************************/
INT32U TOOL_AsciiToDec(INT8U *sptr, INT8U len)
{
    INT32U result;
    
    result = 0;
    
    for (; len > 0; len--) {
        result = result * 10 + TOOL_CharToHex(*sptr++);
    }
    
    return result;
}

/**************************************************************************************************
**  函数名称:  TOOL_DecToAscii
**  功能描述:  将十进制数据转换成ASCII字符串[7899 -----> '7','8','9','9']
**  输入参数:  data:   待转换的hex数据
**             rlen:   转换长度参考值  
**                     [rlen == 0, 则转换结果不受reflen控制]
**                     [rlen != 0, 则转换的字符串长度小于rlen时在字符串前补(rlen-实际长度)个0]
**  输出参数:  dptr:   转换后的字符串缓冲区
**  返回参数:  转换的字符串长度(包括前置0)
**************************************************************************************************/
INT8U TOOL_DecToAscii(INT8U *dptr, INT32U data, INT8U rlen)
{
    INT8U    i, len, temp;
    INT8U   *tempptr;
    
    len     = 0;
    tempptr = dptr;
    
    for (;;) {
        
        *dptr++ = TOOL_HexToChar(data % 10);
        len++;
        
        if (data < 10) {
            break;
        } else {
            data /= 10;
        }
    }
    
    if (len != 0) {
        dptr = tempptr;
        
        for (i = 0; i < (len/2); i++) {
            temp = *(dptr + i);
            *(dptr + i) = *(dptr + (len - 1 - i));
            *(dptr + (len - 1 - i)) = temp;
        }
        
        if (rlen > len) {
            dptr = tempptr + (len - 1);
            
            for (i = 1; i <= rlen; i++) {
                if (i <= len) {
                    *(dptr + (rlen - len)) = *dptr;
                } else {
                    *(dptr + (rlen - len)) = '0';
                }
                dptr--;
            }
            
            len = rlen;
        }
    }
    
    return len;
}

/**************************************************************************************************
**  函数名称:  TOOL_GetChkSum_O
**  功能描述:  计算逐个字节累加校验码, 取最低字节
**  输入参数:  dptr: 数据区地址; len: 数据区长度
**  输出参数:  无
**  返回参数:  单字节累加校验码
**************************************************************************************************/
INT8U TOOL_GetChkSum_O(INT8U *dptr, INT32U len)
{
    INT8U result;
	
    result = 0;
    
    for (; len > 0; len--) {
        result += *dptr++;
    }
    
    return result;
}

/**************************************************************************************************
**  函数名称:  TOOL_GetChkSum_N
**  功能描述:  计算逐个字节取反后累加校验码, 取最低字节
**  输入参数:  dptr: 数据区地址; len: 数据区长度
**  输出参数:  无
**  返回参数:  单字节累加校验码
**************************************************************************************************/
INT8U TOOL_GetChkSum_N(INT8U *dptr, INT32U len)
{
    INT8U result;
	
    result = 0;
    
    for (; len > 0; len--) {
        result += (INT8U)(~(*dptr++));
    }
    
    return result;
}

/**************************************************************************************************
**  函数名称:  TOOL_GetChkSum_X
**  功能描述:  计算逐个字节异或校验码
**  输入参数:  dptr: 数据区地址; len: 数据区长度
**  输出参数:  无
**  返回参数:  校验码
**************************************************************************************************/
INT8U TOOL_GetChkSum_X(INT8U *dptr, INT32U len)
{
    INT8U result;
	
    result = 0;
    
    for (; len > 0; len--) {
        result ^= *dptr++;
    }
    
    return result;
}

/**************************************************************************************************
**  函数名称:  TOOL_SearchKeyWord
**  功能描述:  寻找关键字符串
**  输入参数:  无
**  输出参数:  无
**  返回参数:  无
**************************************************************************************************/
BOOLEAN TOOL_SearchKeyWord(BOOLEAN matchcase, INT8U *dptr, INT16U dlen, char *sptr)
{
    INT8U ch1, ch2;
    
    if (*sptr == 0) {
        return false;
    }
    
    while(dlen > 0) {
        
        ch1 = *dptr++;
        ch2 = *sptr++;
        
        if (!matchcase) {
            ch1 = TOOL_LowerChar(ch1);
            ch2 = TOOL_LowerChar(ch2);
        }
        
        if (ch1 == ch2) {
            if (*sptr == 0) {
                return true;
            }
        } else {
            return false;
        }
        
        dlen--;
    }
    
    return false;
}

/**************************************************************************************************
**  函数名称:  TOOL_Assemblebyrule
**  功能描述:  封装协议
**  输入参数:  无
**  输出参数:  无
**  返回参数:  无
**************************************************************************************************/
INT16U TOOL_AssembleByRules(INT8U *dptr, INT16U dlen, INT8U *sptr, INT16U slen, ASMRULE_T const *rule)
{
    INT8U  temp;
    INT16U rlen;
    
    if (rule == 0) {
        return 0;
    }
    
    *dptr++ = rule->c_flags;
    rlen    = 1;
    for (; slen > 0; slen--) {
        temp = *sptr++;
        if (temp == rule->c_flags) {
            if (rlen < dlen - 2) {
                *dptr++ = rule->c_convert0;
                *dptr++ = rule->c_convert1;
                 rlen += 2;
             } else {
                 return 0;
             }
        } else if (temp == rule->c_convert0) {
            if (rlen < dlen - 2) {
                *dptr++ = rule->c_convert0;
                *dptr++ = rule->c_convert2;
                rlen += 2;
            } else {
                return 0;
            }
        } else {
            if (rlen < dlen - 1) {
                *dptr++ = temp;
                rlen++;
            } else {
                 return 0;
             }
        }
    }
    
    *dptr = rule->c_flags;
    rlen++;
    return rlen;
}

/**************************************************************************************************
**  函数名称:  TOOL_DeassembleByRules
**  功能描述:  解封协议
**  输入参数:  无
**  输出参数:  无
**  返回参数:  无
**************************************************************************************************/
INT16U TOOL_DeassembleByRules(INT8U *dptr, INT16U dlen, INT8U *sptr, INT16U slen, ASMRULE_T const *rule)
{
    INT16U rlen;
    INT8U  prechar, curchar, c_convert0;
    
    if (rule == 0) {
        return 0;
    }
    
    c_convert0 = rule->c_convert0;
    rlen = 0;
    prechar = (~c_convert0);
    for (; slen > 0; slen--) {
        curchar = *sptr++;
        if (prechar == c_convert0) {
            if (curchar == rule->c_convert1) {
                prechar = (~c_convert0);
                if (rlen < dlen) {
                    *dptr++ = rule->c_flags;
                    rlen++;
                } else {
                    return 0;
                }
            } else if (curchar == rule->c_convert2) {
                prechar = (~c_convert0);
                if (rlen < dlen) {
                    *dptr++ = c_convert0;
                    rlen++;
                } else {
                    return 0;
                }
            } else {
                return 0;
            }
        } else {
            if ((prechar = curchar) != c_convert0) {
                if (rlen < dlen) {
                    *dptr++ = curchar;
                    rlen++;
                } else {
                    return 0;
                }
            }
        }
    }
    return rlen;
}

/**************************************************************************************************
**  函数名称:  Assemble8Uto32U
**  功能描述:  将连续4个INT8U的数据拼合成一个INT32U的数据
**  输入参数:  无
**  输出参数:  无
**  返回参数:  无
**************************************************************************************************/
INT32U TOOL_Assemble8Uto32U(INT8U *dptr)
{
    INT32U result;
    
    result  = (INT32U)((*dptr++) << 24);
    result += (INT32U)((*dptr++) << 16);
    result += (INT32U)((*dptr++) << 8);
    result += (INT32U)((*dptr++));
    
    return result;
}

/**************************************************************************************************
**  函数名称:  Disassemble32Uto8U
**  功能描述:  拆分INT32U的数据填充到INT8U数组中
**  输入参数:  无
**  输出参数:  无
**  返回参数:  无
**************************************************************************************************/
INT8U TOOL_Disassemble32Uto8U(INT8U *dptr, INT32U data)
{
    *dptr++ = (INT8U)(data >> 24);
    *dptr++ = (INT8U)(data >> 16);
    *dptr++ = (INT8U)(data >> 8);
    *dptr++ = (INT8U)(data & 0xFF);
    
    return 4;
}

/**************************************************************************************************
**  函数名称:  TOOL_GetTimeStamp
**  功能描述:  根据输入的日期和时间, 计算对应的秒
**  输入参数:  time: 输入时间
**  输出参数:  无
**  返回参数:  GPS秒数, 自2000年1月1日零时起算
**************************************************************************************************/
INT32U TOOL_GetTimeStamp(SYSTIME_T *time)
{
    INT8U  i;
    INT16U days, year;

    year = time->date.year;
    
    if (year == 0) {                                                           /* 2000年 */
        days = 0;
    } else {
        days = year * 365 + ((year - 1) / 4 + 1);
    }
    
    for (i = 1; i < time->date.month; i++) {
        days += s_month[i - 1];
    }
    
    if ((time->date.month > 2) && (time->date.year % 4) == 0) {
        days++;
    }
    
    days += time->date.day - 1;
    
    return (days * (24 * 3600) + time->time.hour * 3600 - 8 * 3600 + time->time.minute * 60 + time->time.second);
}

/**************************************************************************************************
**  函数名称:  TOOL_ConvertTimeStamp
**  功能描述:  根据时间戳转换为日期时间格式
**  输入参数:  无
**  输出参数:  无
**  返回参数:  无
**************************************************************************************************/
void TOOL_ConvertTimeStamp(SYSTIME_T *time, INT32U stamp)
{
    INT8U  i;
    INT32U user, temp;
    
    stamp += 8 * 3600;
    
    time->date.year  = 0;                                                      /* 2000年1月1日 */
    time->date.month = 1;
    time->date.day   = 1;
    
    time->date.year = stamp / (3600 * 24 * 365);                               /* 计算年 */
    
    if (time->date.year > 1) {
        user = (time->date.year * 365 + ((time->date.year - 1) / 4 + 1)) * 3600 * 24;
        if (user > stamp) {
            time->date.year--;
            user = (time->date.year * 365 + ((time->date.year - 1) / 4 + 1)) * 3600 * 24;
        }
    } else {
        user = 0;
    }
    
    stamp -= user;
    
    user = stamp / (3600 * 24);                                                /* 计算月 */
    temp = 0;
    
    for (i = 0; i < 12; i++) {
        temp = s_month[i];
        if ((i == 1) && (time->date.year % 4) == 0) {
            temp++;
        }
        if (user >= temp) {
            user -= temp;
            time->date.month++;
        }
    }
    
    time->date.day += user;                                                    /* 计算日 */
    
    time->time.hour   = (stamp % (3600 * 24)) / 3600;
    time->time.minute = (stamp % 3600) / 60;
    time->time.second = (stamp % 60);
}



